//
//  NSString+BZHTML.m
//  BZFoundation
//
//  Created by 郭艺伟 on 2017/10/1.
//  Copyright © 2017年 郭艺伟. All rights reserved.
//

#import "NSString+BZHTML.h"

@implementation NSString (BZHTML)
- (NSString *)bz_hostString {
    if ([self length] == 0) {
        return nil;
    }
    
    NSURL *url = [NSURL URLWithString:self];
    if (!url) {
        return nil;
    }
    
    return [url host];
}

- (NSString *)bz_URLEncodedString {
    CFStringRef stringRef = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                    (CFStringRef)self,
                                                                    NULL,
                                                                    CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"),
                                                                    kCFStringEncodingUTF8);
    NSString *encodedString = (__bridge NSString *)stringRef;
    CFRelease(stringRef);
    
    if (encodedString) {
        return encodedString;
    }
    
    return nil;
}

- (NSString *)bz_escapeHTML {
    NSMutableString *s = [NSMutableString string];
    
    NSUInteger start = 0;
    NSUInteger len = [self length];
    NSCharacterSet *chs = [NSCharacterSet characterSetWithCharactersInString:@" <>&\""];
    
    while (start < len) {
        NSRange r = [self rangeOfCharacterFromSet:chs options:NSCaseInsensitiveSearch range:NSMakeRange(start, len-start)];
        if (r.location == NSNotFound) {
            [s appendString:[self substringFromIndex:start]];
            break;
        }
        
        if (start < r.location) {
            [s appendString:[self substringWithRange:NSMakeRange(start, r.location-start)]];
        }
        
        switch ([self characterAtIndex:r.location]) {
            case '<':
                [s appendString:@"&lt;"];
                break;
            case '>':
                [s appendString:@"&gt;"];
                break;
            case '"':
                [s appendString:@"&quot;"];
                break;
            case '&':
                [s appendString:@"&amp;"];
                break;
            case ' ':
                [s appendString:@"&nbsp;"];
                break;
        }
        
        start = r.location + 1;
    }
    
    return [s copy];
}

- (NSString *)bz_unescapeHTML {
    NSMutableString *s = [NSMutableString string];
    NSMutableString *target = [self mutableCopy];
    NSCharacterSet *chs = [NSCharacterSet characterSetWithCharactersInString:@"&"];
    
    while ([target length] > 0) {
        NSRange r = [target rangeOfCharacterFromSet:chs];
        if (r.location == NSNotFound) {
            [s appendString:target];
            break;
        }
        
        if (r.location > 0) {
            [s appendString:[target substringToIndex:r.location]];
            [target deleteCharactersInRange:NSMakeRange(0, r.location)];
        }
        
        if ([target hasPrefix:@"&lt;"]) {
            [s appendString:@"<"];
            [target deleteCharactersInRange:NSMakeRange(0, 4)];
        } else if ([target hasPrefix:@"&gt;"]) {
            [s appendString:@">"];
            [target deleteCharactersInRange:NSMakeRange(0, 4)];
        } else if ([target hasPrefix:@"&quot;"]) {
            [s appendString:@"\""];
            [target deleteCharactersInRange:NSMakeRange(0, 6)];
        } else if ([target hasPrefix:@"&#39;"]) {
            [s appendString:@"'"];
            [target deleteCharactersInRange:NSMakeRange(0, 5)];
        } else if ([target hasPrefix:@"&amp;"]) {
            [s appendString:@"&"];
            [target deleteCharactersInRange:NSMakeRange(0, 5)];
        } else if ([target hasPrefix:@"&hellip;"]) {
            [s appendString:@"…"];
            [target deleteCharactersInRange:NSMakeRange(0, 8)];
        } else if ([target hasPrefix:@"&nbsp;"]) {
            [s appendString:@" "];
            [target deleteCharactersInRange:NSMakeRange(0, 6)];
        } else {
            [s appendString:@"&"];
            [target deleteCharactersInRange:NSMakeRange(0, 1)];
        }
    }
    
    return [s copy];
}

- (NSString *)bz_stringByAddHTMLUrlLinkTag {
    if (self.length == 0) {
        return self;
    }
    
    NSDataDetector *detect = [[NSDataDetector alloc] initWithTypes:NSTextCheckingTypeLink error:nil];
    NSArray *urls = [detect matchesInString:self options:0 range:NSMakeRange(0, [self length])];;
    NSString *stringSrc = [self copy];
    
    __block NSString *stringDst = self;
    __block NSRange lastRange = NSMakeRange(0, 0);
    [urls enumerateObjectsUsingBlock:^(NSTextCheckingResult *obj, NSUInteger idx, BOOL *stop) {
        if (idx == 0) {
            stringDst = @"";
            stringDst = [stringDst stringByAppendingString:[self substringToIndex:obj.range.location]];
        } else {
            stringDst = [stringDst stringByAppendingString:[self substringWithRange:NSMakeRange(NSMaxRange(lastRange), obj.range.location-NSMaxRange(lastRange))]];
        }
        
        stringDst = [stringDst stringByAppendingFormat:@"<a href=\"%@\">%@</a>", [stringSrc substringWithRange:obj.range], [stringSrc substringWithRange:obj.range]];
        
        // 在没有后续url的时候补齐遗留的字符串
        if ((NSMaxRange(obj.range) < [self length]) && (idx == [urls count]-1)) {
            stringDst = [stringDst stringByAppendingString:[self substringFromIndex:NSMaxRange(obj.range)]];
        }
        
        lastRange = obj.range;
    }];
    
    return stringDst;
}

@end
